﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TorchView.GameContent.Data;
using System.ComponentModel;

namespace TorchView.GameContent.Skills
{
  public sealed class Skill : SkillBase
  {
    public const string BLOCK_NAME = "SKILL";
    public static readonly string[] DECENDANT_TYPES = new string[] { "AFFIXES", "AFFIXESREMOVE", "EFFECTS", "EFFECTSREMOVE", "EVENT", "LEVEL" };

    #region Defaults
    const bool UseWeaponAnim_Default = false;
    const int MaxLevel_Default = 0;
    const bool Hidden_Default = false;
    const bool AllowsTurning_Default = true;
    const bool DontStopOnDeath_Default = false;
    const bool Interruptable_Default = false;
    const bool CanBeSilenced_Default = true;
    const bool ReqPassableLOS_Default = false;
    const bool ReqPathable_Default = false;
    const int Column_Default = -1;
    const int Charges_Default = 0;
    #endregion

    public static Skill LoadSkill(string skillName)
    {
      string filepath = PakReader.GetFiles("media/skills/", skillName + ".dat.adm", System.IO.SearchOption.AllDirectories).FirstOrDefault();
      if (filepath == null)
        return null;
      var stream = PakReader.OpenFile(filepath);
      if (stream == null)
        return null;
      var block = AdmSerializer.Load(stream);
      Skill skill = new Skill();
      skill.LoadFromDataBlock(block);
      return skill;
    }

    protected override string GetBlockName()
    {
      return BLOCK_NAME;
    }

    #region IDataSerializable Members

    protected override void FillBlock(DataBlock block)
    {
      block.SetPropertyValue("NAME", SkillName);
      block.SetPropertyValue("SKILL_TYPE", SkillType);
      block.SetPropertyValue("USAGE_DESCRIPTION", UsageDescription, PropertyType.TRANSLATE);
      block.SetPropertyValue("ACTIVATION_TYPE", ActivationType);
      block.SetPropertyValue("TARGET_ALIGNMENT", TargetAlignment);
      block.SetOrClearPropertyValue(UseWeaponAnim != UseWeaponAnim_Default, "USEWEAPONANIMATION", UseWeaponAnim);
      block.SetOrClearPropertyValue(MaxLevel != MaxLevel_Default, "MAXLEVELS", MaxLevel);
      block.SetPropertyValue("NOTTHEME", RequiredNotTheme);
      block.SetOrClearPropertyValue(Hidden != Hidden_Default, "HIDDEN", Hidden);
      block.SetOrClearPropertyValue(DontStopOnDeath != DontStopOnDeath_Default, "DONT_STOP_ON_DEATH", DontStopOnDeath);
      block.SetOrClearPropertyValue(Interruptable != Interruptable_Default, "INTERRUPTABLE", Interruptable);
      block.SetOrClearPropertyValue(CanBeSilenced != CanBeSilenced_Default, "CAN_BE_SILENCED", CanBeSilenced);
      block.SetOrClearPropertyValue(Column != Column_Default, "COLUMN", Column);
      block.SetOrClearPropertyValue(Charges != Charges_Default, "CHARGES", Charges);
      block.SetOrClearPropertyValue(AllowsTurning != AllowsTurning_Default, "ALLOWS_TURNING", AllowsTurning);
      block.SetOrClearPropertyValue(ReqPassableLOS != ReqPassableLOS_Default, "REQUIRES_PASSABLE_LOS", ReqPassableLOS);
      block.SetOrClearPropertyValue(ReqPathable != ReqPathable_Default, "REQUIRES_PATHABLE", ReqPathable);
      base.FillBlock(block);
    }

    public override void LoadFromDataBlock(DataBlock block)
    {
      if (block == null)
        throw new ArgumentNullException("block");
      if (block.Name != BLOCK_NAME)
        throw new ArgumentException("Incorrect block type, only " + BLOCK_NAME + " is supported.");

      SkillName = block.GetPropertyValue("NAME", "");
      SkillType = block.GetPropertyValue("SKILL_TYPE", "");
      UsageDescription = block.GetPropertyValue("USAGE_DESCRIPTION", "");
      ActivationType = block.GetPropertyValue("ACTIVATION_TYPE", "");
      TargetAlignment = block.GetPropertyValue("TARGET_ALIGNMENT", "");
      MaxLevel = block.GetPropertyValue("MAXLEVELS", MaxLevel_Default);
      UseWeaponAnim = block.GetPropertyValue("USEWEAPONANIMATION", UseWeaponAnim_Default);
      RequiredNotTheme = block.GetPropertyValue("NOTTHEME", "");
      Interruptable = block.GetPropertyValue("INTERRUPTABLE", Interruptable_Default);
      CanBeSilenced = block.GetPropertyValue("CAN_BE_SILENCED", CanBeSilenced_Default);
      Column = block.GetPropertyValue("COLUMN", Column_Default);
      Charges = block.GetPropertyValue("CHARGES", Charges_Default);
      Hidden = block.GetPropertyValue("HIDDEN", Hidden_Default);
      AllowsTurning = block.GetPropertyValue("ALLOWS_TURNING", AllowsTurning_Default);
      DontStopOnDeath = block.GetPropertyValue("DONT_STOP_ON_DEATH", DontStopOnDeath_Default);
      ReqPassableLOS = block.GetPropertyValue("REQUIRES_PASSABLE_LOS", ReqPassableLOS_Default);
      ReqPathable = block.GetPropertyValue("REQUIRES_PATHABLE", ReqPathable_Default);

      base.LoadFromDataBlock(block);
    }

    #endregion

    protected override IDataSerializable GetDecendant(DataBlock block)
    {
      if (block.Name.StartsWith(SkillLevel.BLOCK_NAME))
      {
        SkillLevel level = new SkillLevel();
        level.LoadFromDataBlock(block);
        return level;
      }
      return base.GetDecendant(block);
    }

    // Properties
    [DisplayName("Activation"), Category("~Skill Globals"), Description("Activation Type")]
    public string ActivationType { get; set; }

    [Category("~Skill Globals"), Description("Can Turn while performing skill"), DisplayName("Allow Turning")]
    public bool AllowsTurning { get; set; }

    [Category("~Skill Globals"), DisplayName("Charges"), Description("# of charges the skill has")]
    public int Charges { get; set; }

    [DisplayName("Column (UI)"), Description("Column in the skill UI pane (-1 for no column)"), Category("~Skill Globals")]
    public int Column { get; set; }

    [Category("Skill"), DisplayName("Can be Silenced"), Description("Can this skill be silenced?")]
    public bool CanBeSilenced { get; set; }

    [Category("~Skill Globals"), Description("Does the skill stop upon caster death?"), DisplayName("Don't Stop on Death")]
    public bool DontStopOnDeath { get; set; }

    [Description("Skill is hidden from player and AI"), Category("~Skill Globals"), DisplayName("Hidden")]
    public bool Hidden { get; set; }

    [DisplayName("Interruptable"), Category("Skill"), Description("Skill is Interruptable")]
    public bool Interruptable { get; set; }

    [Browsable(false), DisplayName("Max Levels"), Category("Skill"), Description("Maximum number of skill levels")]
    public int MaxLevel { get; set; }

    [Category("~Skill Globals"), Description("Skill Requires a passable Line of Sight to target"), DisplayName("Req. Passable LOS")]
    public bool ReqPassableLOS { get; set; }

    [Description("Skill Require Pathable target"), Category("~Skill Globals"), DisplayName("Req Pathable")]
    public bool ReqPathable { get; set; }

    [DisplayName("Not Theme"), Description("Theme which will block this skill from firing"), Category("Requirements")]
    public string RequiredNotTheme { get; set; }

    [Description("Name of Skill"), DisplayName("Name"), Category("~Skill Globals"), Browsable(true)]
    public string SkillName { get; set; }

    [Browsable(true), Category("~Skill Globals"), Description("Type of Skill"), DisplayName("Skill Type")]
    public string SkillType { get; set; }

    [Category("~Skill Globals"), Description("Skill targets units of this alignment"), DisplayName("Target Alignment")]
    public string TargetAlignment { get; set; }

    [Category("~Skill Strings"), DisplayName("Usage Desc."), Description("Usage Description of Skill")]
    public string UsageDescription { get; set; }

    [Category("Animation"), Description("Skill uses equipped weapon animation"), DisplayName("Use Weapon Anim")]
    public bool UseWeaponAnim { get; set; }
  }
}
